﻿<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:my="my"
>
  <xsl:output method="text" indent="no" encoding="ascii"/>
  <xsl:param name="outputFile"/>
  <xsl:param name="compatMode"/>

  <!-- File Body -->
  
  <xsl:template match="EseParams">
    <xsl:text/><![CDATA[// ---------------------------------------------------------------------------
// <copyright file="]]><xsl:value-of select="$outputFile"/><![CDATA[" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//
// </copyright>]]>
// ---------------------------------------------------------------------------

//    			  DO NOT EDIT THIS FILE DIRECTLY!
//
// This file is autogenerated from sysparam.xml using DatabaseConfig.xsl, with compatMode = "<xsl:value-of select="$compatMode"/>"
// To modify or add new params, make changes to sysparam.xml and then run gengen.bat to update the source files.

namespace Microsoft.Database.Isam.Config
{
    using System;
    using Microsoft.Isam.Esent.Interop;<xsl:text/>
    <xsl:if test="$compatMode = 'Unpublished'">
    using Microsoft.Isam.Esent.Interop.Unpublished;<xsl:text/>
    </xsl:if>
    using Microsoft.Isam.Esent.Interop.Vista;
    using Microsoft.Isam.Esent.Interop.Windows7;
    using Microsoft.Isam.Esent.Interop.Windows8;
    using Microsoft.Isam.Esent.Interop.Windows81;

    <![CDATA[/// <summary>
    /// A class that contains all engine wide Ese parameters.
    /// </summary>
    public partial class DatabaseConfig : ConfigSetBase
    {]]><xsl:text/>

    <!-- Loop over all Param nodes and generate the params definition table -->
    <!-- Only generate in $compatMode = ''. We don't want to define this twice. -->
    <xsl:if test="$compatMode = ''">
        <![CDATA[/// <summary>
        /// The exclusive upper bound on JET_param*.
        /// </summary>]]>
        internal const int ParamMaxValueInvalid = <xsl:value-of select="count(Param) - 1"/>; // should be equal to JET_paramMaxValueInvalid
    </xsl:if>
        <![CDATA[/// <summary>
        /// Fills the param table from auto-generated code.
        /// </summary>]]>
        static partial void <xsl:value-of select="$compatMode"/>FillParamTable()
        {<xsl:text/>
    <xsl:for-each select="*">
      <!-- if compatibility mode is 'Unpublished', only generate params matching that.
            Otherwise generate all except params with @Compatibility = 'Unpublished'.
      -->
      <xsl:if test="($compatMode = '' and not(@Compatibility = 'Unpublished')) or ($compatMode = 'Unpublished' and @Compatibility = 'Unpublished')">
        <!-- Ignore internal params or params that can't be set. Unwanted macros are filtered out below in the param template -->
        <xsl:if test="not(@Visibility = 'Internal')">
          <xsl:apply-templates select="." mode="ParamTable">
            <xsl:with-param name="id" select="position() - 1"/>
          </xsl:apply-templates>
        </xsl:if>
      </xsl:if>
    </xsl:for-each>
        }&#10;<xsl:text/>

    <!-- Loop over all Param nodes and generate the param properties -->
    <xsl:for-each select="*">
      <!-- if compatibility mode is 'Unpublished', only generate params matching that.
            Otherwise generate all except params with @Compatibility = 'Unpublished'.
      -->
      <xsl:if test="($compatMode = '' and not(@Compatibility = 'Unpublished')) or ($compatMode = 'Unpublished' and @Compatibility = 'Unpublished')">
        <xsl:choose>
          <xsl:when test="@Visibility = 'Internal'"/>
          <xsl:when test="@Visibility = 'HideOnWSA'">
            <xsl:text>&#10;#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK</xsl:text>
            <xsl:apply-templates select="." mode="ParamProps">
              <xsl:with-param name="id" select="position() - 1"/>
            </xsl:apply-templates>
            <xsl:text>#endif&#10;</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="." mode="ParamProps">
              <xsl:with-param name="id" select="position() - 1"/>
            </xsl:apply-templates>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:if>
    </xsl:for-each>
    }
}
<xsl:text />
  </xsl:template>

  <!-- Default type mapping between native and managed types (when ManagedType attribute isn't specified).
       _bad_type_* require the user to specify ManagedType. Otherwise we generate code that can't compile.
  -->
  <my:DataTypeTable>
    <my:Type key="typeBoolean">bool</my:Type>
    <my:Type key="typeGrbit">_bad_type_grbit</my:Type>
    <my:Type key="typeInteger">int</my:Type>
    <my:Type key="typeString">string</my:Type>
    <my:Type key="typePointer">IntPtr</my:Type>
    <my:Type key="typeFolder">string</my:Type>
    <my:Type key="typePath">string</my:Type>
    <my:Type key="typeBlockSize">int</my:Type>
    <my:Type key="typeUserDefined">_bad_type_userdefined</my:Type>
  </my:DataTypeTable>

  <xsl:key name="dataTypeTable" match="my:Type" use="@key"/>
  <xsl:variable name="nodeDataTypeTable" select="document('')/*/my:DataTypeTable"/>

  <!-- A template to generate one row in the globalParams array -->
  <xsl:template match="Param" mode="ParamTable">
    <xsl:param name="id"/>
    <xsl:if test="@Macro = 'NormalParam' or @Macro = 'NormalParam2' or @Macro = 'CustomParam' or @Macro = 'CustomParam2' or @Macro = 'CustomParam3' or @Macro = 'ReadonlyParam'">
      <xsl:text>&#10;            DatabaseConfig.ParamTable[</xsl:text><xsl:value-of select="$id"/>] = new ParamDef(<xsl:value-of select="$id"/>, <xsl:call-template name="valueOrDefault"><xsl:with-param name="value" select="@StaticAfterGlobalInit"/><xsl:with-param name="default" select="'false'"/></xsl:call-template>, typeof(<xsl:apply-templates select="@Type"/>)); // <xsl:value-of select="@Name"/>
    </xsl:if>
  </xsl:template>

  <!-- A template to generate param proprerties -->
  <xsl:template match="Param" mode="ParamProps">
    <xsl:param name="id"/>
    <xsl:if test="@Macro = 'NormalParam' or @Macro = 'NormalParam2' or @Macro = 'CustomParam' or @Macro = 'CustomParam2' or @Macro = 'CustomParam3' or @Macro = 'ReadonlyParam'">
      <xsl:variable name="readonly" select="@Macro = 'ReadonlyParam' or @Set = 'CJetParam::IllegalSet'"/>
      <xsl:call-template name="Documentation">  <!-- We want to _call_ this template, so that it executes even if the <Documentation> tag doesn't exist -->
        <xsl:with-param name="readonly" select="$readonly"/>
      </xsl:call-template>
      <xsl:apply-templates select="Comments"/>
        public <xsl:apply-templates select="@Type"/> <xsl:text> </xsl:text> <xsl:apply-templates select="@Name" />
        {
            get { return this.GetParam&lt;<xsl:apply-templates select="@Type"/>&gt;(<xsl:value-of select="$id"/>); }<xsl:text/>
      <xsl:if test="$readonly != 'true'">
            set { this.SetParam(<xsl:value-of select="$id"/>, value); }<xsl:text/>
      </xsl:if>
        }&#10;<xsl:text/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="@Name">
    <xsl:value-of select="substring-after(., 'JET_param')" />
  </xsl:template>

  <xsl:template match="@Type">
    <xsl:choose>
      <xsl:when test="../@ManagedType">
        <xsl:value-of select="../@ManagedType" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="$nodeDataTypeTable">
          <xsl:with-param name="curr_type" select="." />
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
  <!-- Template to lookup curr_type (native type) in the DataTypeTable -->
  <xsl:template match="my:DataTypeTable">
    <xsl:param name="curr_type" />
    <xsl:value-of select="key('dataTypeTable', substring-after(string($curr_type), 'CJetParam::'))"/>
  </xsl:template>

  <!-- Convert Documentation into a summary section -->
  <xsl:template name="Documentation">
    <xsl:param name="readonly"/>
    <![CDATA[    /// <summary>]]><xsl:text/>
    <xsl:choose>
      <xsl:when test="normalize-space(Documentation) != ''">
        <xsl:call-template name="tokenize">
          <xsl:with-param name="text" select="Documentation"/>
          <xsl:with-param name="sep" select="'&#10;'"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        /// Gets <xsl:if test="$readonly != 'true'">or sets </xsl:if><xsl:apply-templates select="@Name"/> of type <xsl:apply-templates select="@Type"/>
      </xsl:otherwise>
    </xsl:choose>
    <![CDATA[    /// </summary>]]><xsl:text/>
  </xsl:template>

  <!-- Convert comments into a remarks section -->
  <xsl:template match="Comments">
    <xsl:if test="normalize-space(.) != ''">
        <![CDATA[/// <remarks>]]><xsl:text/>
      <xsl:call-template name="tokenize">
        <xsl:with-param name="text" select="."/>
        <xsl:with-param name="sep" select="'&#10;'"/>
      </xsl:call-template>
        <![CDATA[/// </remarks>]]><xsl:text/>
    </xsl:if>
  </xsl:template>

  <!-- Template to tokenize a given string on newlines and generate a multi-line comment -->
  <xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="sep"/>
    <xsl:choose>
      <xsl:when test="contains($text, $sep)">
        <xsl:call-template name="gen_comment">
          <xsl:with-param name="text" select="normalize-space(substring-before($text, $sep))"/>
        </xsl:call-template>
        <xsl:call-template name="tokenize">
          <xsl:with-param name="text" select="substring-after($text, $sep)"/>
          <xsl:with-param name="sep" select="$sep"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="gen_comment">
          <xsl:with-param name="text" select="normalize-space($text)"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
  <xsl:template name="gen_comment">
    <xsl:param name="text"/>
    <xsl:if test="$text != ''">
        /// <xsl:value-of select="$text"/>
    </xsl:if>
  </xsl:template>

  <!-- Template to return a value or a given default if the value is empty -->
  <xsl:template name="valueOrDefault">
    <xsl:param name="value"/>
    <xsl:param name="default"/>
    <xsl:choose>
      <xsl:when test="normalize-space($value) != ''">
        <xsl:value-of select="$value"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$default"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
